<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="text" id="inputValue"/>
<button id="btn">打开/创建database</button>
<button id="indexGetBtn">索引获取Donna</button>
<button id="indexCursorGetBtn">索引游标获取所有Donna</button>
<script>
  // 我们的客户数据看起来像这样。
  const customerData = [
    {ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com"},
    {ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org"},
    {ssn: "666-66-6666", name: "Tony", age: 23, email: "ony@home.org"},
    {ssn: "888-88-8888", name: "Donna", age: 27, email: "donna2@home.org"}
  ];
  let db = null
  const openDatabase = function (version) {
    console.log('database version:', version)
    // 如果数据库不存在，open 操作会创建该数据库,第二个参数指定数据库的版本
    const request = window.indexedDB.open('MySecondDatabase', version)

    request.onsuccess = function (event) {
      db = event.target.result
      console.log('database success')
    }

    request.onerror = function (event) {
      console.log('database fail:', event.target.error.message)
    }

    // 当你创建一个新的数据库或者增加已存在的数据库的版本号（当打开数据库时，指定一个比之前更大的版本号）， onupgradeneeded 事件会被触发
    request.onupgradeneeded = function (event) {
      console.log('database onupgradeneeded')

      // 保存 IDBDataBase 接口
      db = event.target.result
      const objectStore = db.createObjectStore('customers', {keyPath: 'ssn'})

      /**
       * 使用 SSN 作为键来存储客户数据是合理的，因为 SSN 唯一地标识了一个个体（对隐私来说这是否是一个好的想法是另外一个话题，不在本文的讨论范围内）。
       * 如果你想要通过姓名来查找一个客户，那么，你将需要在数据库中迭代所有的 SSN 直到你找到正确的那个。
       * 以这种方式来查找将会非常的慢，相反你可以使用索引。
       */
      // 建立一个索引来通过姓名来搜索客户。名字可能会重复，所以我们不能使用 unique 索引
      objectStore.createIndex("name", "name", {unique: false});
      // email不允许重复
      objectStore.createIndex('email', 'email', {unique: true})

      // 使用事务的 oncomplete 事件确保在插入数据前对象仓库已经创建完毕
      objectStore.transaction.oncomplete = function () {
        const transaction = db.transaction('customers', 'readwrite')
        const customersObjectStore = transaction.objectStore('customers')
        customerData.forEach(item => {
          customersObjectStore.add(item)
        })
      }
    }
  }
  btn.addEventListener('click', () => {
    openDatabase(Number(inputValue.value || 1))
  })

  indexGetBtn.addEventListener('click', () => {
    const index = db
      .transaction('customers')
      .objectStore('customers')
      .index('name')  // 使用
    console.log('index:', index)
    // “name” 游标不是唯一的，因此 name 被设成 "Donna" 的记录可能不止一条。在这种情况下，你总是得到键值最小的那个。
    index.get('Donna').onsuccess = function (event) {
      console.log('get Donna:', event.target.result)
    }
  })

  indexCursorGetBtn.addEventListener('click', () => {
    const index = db
      .transaction('customers')
      .objectStore('customers')
      .index('name')
    const donnas = []
    index.openCursor().onsuccess = function (event) {
      const cursor = event.target.result
      if (cursor) {
        // cursor.key 是一个 name, 就像 "Bill", 然后 cursor.value 是整个对象。
        if (cursor.key === 'Donna') {
          donnas.push(cursor.value)
        }
        cursor.continue()
      } else {
        console.log('get all Donna:')
        console.log(donnas)
      }
    }

    index.openKeyCursor().onsuccess = function(event) {
      const cursor = event.target.result;
      if (cursor) {
        // cursor.key 是一个 name, 就像 "Bill", 然后 cursor.primaryKey 是那个 SSN。
        // 没有办法可以得到存储对象的其余部分。
        console.warn("Name: " + cursor.key + ", SSN: " + cursor.primaryKey);
        cursor.continue();
      }
    };
  })
</script>
</body>
</html>
